package fun.easycode.webterminal.common.config;

import fun.easycode.webterminal.common.contract.*;
import fun.easycode.webterminal.common.util.ClassUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.time.LocalDateTime;

@Configuration
@Slf4j
public class MvcConfig implements WebMvcConfigurer, Jackson2ObjectMapperBuilderCustomizer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController( "/{path:[^\\.]*}").setViewName("index");
    }

    /**
     * mvc枚举转换器
     * @return EnumeratorConvertFactory
     */
    @Bean
    public EnumeratorConvertFactory enumeratorConvertFactory(){
        return new EnumeratorConvertFactory();
    }

    /**
     * mvc LocalDateTime转换器 前台时间戳直接转LocalDateTime
     * @return LocalDateTimeConvertFactory
     */
    @Bean
    public LocalDateTimeConvertFactory localDateTimeConvertFactory(){
        return new LocalDateTimeConvertFactory();
    }

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverterFactory(enumeratorConvertFactory());
        registry.addConverterFactory(localDateTimeConvertFactory());
    }

    @Override
    public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
        log.info("customize jackson2ObjectMapperBuilder");
        // 配置枚举自定义序列化规则，必须继承Enumerator接口
        // 反序列化需要自己使用注解，或者指定全局的具体类型，这里配置不好使, 然后就是这里的配置不好使，只能用下面的方法
        // jacksonObjectMapperBuilder.deserializerByType(Enumerator.class, new EnumeratorDeserializer());
        ClassUtil.getAllClassByInterface(Enumerator.class).forEach(clazz -> {
            log.info("register enumerator: {}", clazz.getName());
            jacksonObjectMapperBuilder.deserializerByType(clazz, new EnumeratorDeserializer());
        });
        jacksonObjectMapperBuilder.serializerByType(Enumerator.class, new EnumeratorSerializer());
        // 配置LocalDateTime规则，时间戳
        jacksonObjectMapperBuilder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer());
        jacksonObjectMapperBuilder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer());
    }

    @Bean
    public RequestInterceptor logInterceptor(){
        return new RequestInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(logInterceptor());
        // 可以具体指定哪些需要拦截，哪些不拦截，其实也可以使用自定义注解更灵活完成
        // .addPathPatterns("/**")
        // .excludePathPatterns("/xxx.yyy");
    }
}
